class Database(object):
    
    """The database baseclass."""
    
    def query(self, query, params=()):
        """Exectute the SELECT query with the given parameters
        
            This method can only be used for SELECT queries.
            For INSERT, UPDATE, DELETE, use the modfiy method.
        """
        raise NotImplementedError("This method is not implemented")

    def get(self, table, **row):
        """
            Execute the query, return the first item or raise KeyError
        """
        where_string = ' and '.join('%s=?'%k for k in row.keys())
        query = 'SELECT * FROM %s WHERE %s'%(table, where_string)
        result = self.query(query, row.values())
        return result

    def getOne(self, table, **row):
        """
            Execute the query, return the first item or raise KeyError
        """
        result = self.get(table, **row).fetchone()
        if result:
            return dict(result)
        else:
            raise KeyError

    def insert(self, table, **row):
        columns = ', '.join(row.keys())
        values = ', '.join('?' for k in row)
        query = "INSERT INTO %s (%s) VALUES (%s)" % (table, columns, values)
        return self.modify(query, row.values())

    def select_or_insert(self, table, **row):
        where_string = ' and '.join('%s=?'%k for k in row.keys())
        query = 'SELECT * FROM %s WHERE %s'%(table, where_string)
        r = self.query(query, row.values()).fetchone()
        if not r:
            self.insert(table, row)
            r = self.query(query, row.values()).fetchone()
        return dict(r)

    def update(self, table, where_columns, **row):
        # todo: use column info to determine PK instead of passing where cols
        if isinstance(where_columns, basestring):
            where_columns = [where_columns]
        where_string = ' and '.join('%s=?'%k for k in where_columns)
        where_values = [row[k] for k in where_columns]
        update_string = ', '.join('%s=?'%k for k in row.keys())
        update_values = row.values()
        query = 'UPDATE %s SET %s WHERE %s' % (table, 
                                               update_string,
                                               where_string)
        return self.modify(query, update_values + where_values)

    def delete_rows(self, table, **row):
        where_string = ' and '.join('%s=?'%k for k in row.keys())
        query = 'DELETE FROM %s WHERE %s'%(table, where_string)
        self.modify(query, row.values())
        return None
     
    def dict_query(self, query, params=()):
        """Execute the query, returning a dict or dict of dicts.
            
            The first column in the result will be used as the key.
            If there is only 2 columns the 2nd column will be the value.
            Otherwise the value will be a dictionary of the rest of the columns.
        """
        rows = self.query(query, params)
        result = {}
        for row in rows:
            if len(row) == 2:
                 result[row[0]] = row[1]
            else:
                d = dict(row)
                d.pop(row.keys()[0])
                result[row[0]] = d
        return result
        
    def modify(self, query, params=()):
        """Exectute the query with the given parameters
        
            This method should be used for INSERT, UPDATE and DELETE queries.
            The query will be wrapped in a transaction (if supported)
        """
        raise NotImplementedError("This method is not implemented")
                
    def has_table(self, table):
        """Return True if the specified table exists in this database."""
        raise NotImplementedError("This method is not implemented")
        
    def columns(self, table):
        """List the columns of the table"""
        raise NotImplementedError("This method is not implemented")